import {
  SetBase,
} from './base';

export class SetBaseMap extends SetBase<SetBaseMap, Map<any, any>> {
  public constructor(eles: any[] = []) {
    super(SetBaseMap, new Map(), eles);
  }

  public add(ele) {
    if (!this.has(ele)) {
      this.items.set(ele, ele);
      return true;
    } else {
      return false;
    }
  }

  public delete(ele) {
    if (this.has(ele)) {
      this.items.delete(ele);
      return true;
    } else {
      return false;
    }
  }

  public has(ele) {
    // Avoid 'has' being overwritten
    return Map.prototype.has.call(this.items, ele);
  }

  public clear() {
    this.items.clear();
  }

  public size() {
    return this.items.size;
  }

  public values() {
    return [...this.items.values()];
  }
}

export class SetBaseArray extends SetBase<SetBaseArray, any[]> {
  public constructor(eles: any[] =[]) {
    super(SetBaseArray, [], eles);
  }

  public add(ele) {
    if (!this.has(ele)) {
      this.items.push(ele);
      return true;
    } else {
      return false;
    }
  }

  public delete(ele) {
    let idx = this.getEleIndex(ele); 
    if (idx > -1) {
      this.items.splice(idx, 1);
      return true;
    } else {
      return false;
    }
  }

  public has(ele) {
    return this.getEleIndex(ele) > -1;
  }

  public clear() {
    this.items = [];
  }

  public size() {
    return this.items.length;
  }

  public values() {
    return [...this[Symbol.iterator]()];
  }

  protected [Symbol.iterator] = function *() {
    if (this instanceof SetBaseArray) {
      let indexNext = 0;
      while(indexNext < this.items.length) {
        yield this.items[indexNext];
        indexNext++;
      }
    } else {
      return new Error(`this is ${this}`);
    }
  }

  protected getEleIndex(ele) {
    return Array.prototype.indexOf.call(this.items, ele);
  }
}
